package com.liang.moshijson

import com.squareup.moshi.JsonAdapter
import com.squareup.moshi.Moshi
import com.squareup.moshi.Types
import java.lang.reflect.Type

/**
 * 描述: Boolean，Double，Float，Int，Integer，Long，String
 *      List，Set
 * @author suzl
 * @createTime 2021/6/25
 */
object NullJsonFactory {

    val STANDARD = newStandardFactory()

    /**
     * 是否兼容类型错误
     */
    @JvmStatic
    fun newStandardFactory(allowTypeError: Boolean = false): JsonAdapter.Factory {
        return StandardFactory(allowTypeError)
    }

    internal class StandardFactory(private val allowTypeError: Boolean) : JsonAdapter.Factory {
        override fun create(
            type: Type, annotations: MutableSet<out Annotation>, moshi: Moshi
        ): JsonAdapter<*>? {
            return when (type) {
                Boolean::class.java -> NullBooleanAdapter(allowTypeError)
                Double::class.java -> NullDoubleAdapter(allowTypeError)
                Float::class.java -> NullFloatAdapter(allowTypeError)
                Int::class.java, Integer::class.java -> NullIntAdapter(allowTypeError)
                Long::class.java -> NullLongAdapter(allowTypeError)
                String::class.java -> NullStringAdapter(allowTypeError)
                else -> {
                    val rawType = Types.getRawType(type)
                    return when {
                        annotations.isNotEmpty() -> null
                        rawType == List::class.java -> createListAdapter(
                            type,
                            moshi,
                            allowTypeError
                        )
                        rawType == Set::class.java -> createSetAdapter(type, moshi, allowTypeError)
                        else -> null
                    }
                }
            }
        }

        private fun createListAdapter(
            type: Type, moShi: Moshi, allowTypeError: Boolean
        ): JsonAdapter<*> {
            val elementType = Types.collectionElementType(type, MutableCollection::class.java)
            val elementAdapter: JsonAdapter<Any> = moShi.adapter(elementType)
            return NullListAdapter(elementAdapter, allowTypeError)
        }

        private fun createSetAdapter(
            type: Type, moShi: Moshi, allowTypeError: Boolean
        ): JsonAdapter<*> {
            val elementType = Types.collectionElementType(type, MutableCollection::class.java)
            val elementAdapter: JsonAdapter<Any> = moShi.adapter(elementType)
            return NullSetAdapter(elementAdapter, allowTypeError)
        }
    }
}